package com.example;

import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.builder.Controller;
import com.baomidou.mybatisplus.generator.config.builder.Entity;
import com.baomidou.mybatisplus.generator.config.builder.Mapper;
import com.baomidou.mybatisplus.generator.config.builder.Service;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;

/**
 * 代码生成器
 */
public class CodeGenerator {
    // 数据库IP
    private static final String dbHost = "127.0.0.1";
    // 数据库端口
    private static final String dbPort = "3306";
    // 要使用的库名称
    private static final String dbName = "job_manager";
    // 数据库用户名
    private static final String userName = "root";
    // 数据库连接密码
    private static final String password = "1234";
    // 代码生成路径
    private static final String outputPath = "E:\\project\\java\\springboot-template\\src\\main\\java\\";
    // 作者名称
    private static final String author = "fengzheng";
    // 顶级包名
    private static final String packageName = "com.example";
    // 模块名
    private static final String moduleName = "";

    private static final String url = "jdbc:mysql://" + dbHost + ":" + dbPort + "/" + dbName + "?characterEncoding=utf8&serverTimezone=Asia/Shanghai";

    public static void main(String[] args) {
        FastAutoGenerator generator = FastAutoGenerator.create(url, userName, password);

        // 全局配置
        generator.globalConfig(builder -> {
            // 设置作者，这里设置的作者会标注在每个类的注释中
            builder.author(author);
            // 是否启用Swagger，如果启用会在接口和实体类上使用Swagger注解进行标注
            builder.enableSwagger();
            // 是否覆盖存在的文件，不设置这个选项将不会进行覆盖
            builder.fileOverride();
            // 设置输出目录，这里要使用绝对路径
            builder.outputDir(outputPath);
        });

        // 包配置
        generator.packageConfig(builder -> {
            // 指定父级包名，即顶层包名称
            builder.parent(packageName);
            // 设置模块名称，如果这里进行指定，最后的包名 = 父级包名.模块名称
            builder.moduleName(moduleName);
            // 设置实体类包名
            builder.entity("entity");
            // 设置服务类包名
            builder.service("service");
            // 设置服务实现类包名
            builder.serviceImpl("service.impl");
            // 设置mapper接口包名
            builder.mapper("mapper");
            // 设置xml所在位置包名
            builder.xml("mapper");
            // 设置控制器包名
            builder.controller("controller");
            // 设置自定义文件包名
            builder.other("other");
        });

        // 策略配置
        generator.strategyConfig(builder -> {
            // 是否开启大写命名，始终为True，可省略这个配置
            builder.enableCapitalMode();
            // 过滤表前缀，这里指定需要过滤的字段，比如 user_info 表，指定过滤 user 后生成的Java类会自动去除User，实体类会命名为Info，
            // Controller会命名为 InfoController
            //builder.addTablePrefix("user");
            // 过滤表后缀，规则同 addTablePrefix()，在生成Java类时会省略掉指定的后缀
            //builder.addTableSuffix("info");
            // 过滤属性前缀，会将表中的字段前缀进行过滤，如这里过滤 user，在生成Java实体类时，user_id字段会生成名为id的属性名，
            // user_name字段会生成名为name的属性名
            //builder.addFieldPrefix("user");
            // 过滤属性后缀，用法规则同 addFieldPrefix()
            //builder.addFieldSuffix("name");
            // 要使用的数据表，在这里配置后，生成器在生成前会进行
            // show table status WHERE 1=1  AND NAME IN ('user_info')
            // 的查询，所以这里添加后，只会生成 user_info 表的Java类
            //builder.addInclude("user_info");
            // 添加要排除的表名，与 addInclude() 方法只能二选一
            //builder.addExclude("");
            // 添加要创建的表名，这里配置后，生成器会进行
            // show table status WHERE 1=1  AND NAME LIKE '%user%'
            // 的模糊查询
            //builder.likeTable(new LikeTable("user"));
            // 要排除的表名，与 likeTable 只能二选一
            //builder.notLikeTable(new LikeTable("user"));
        });

        // 模板配置
        generator.templateEngine(new FreemarkerTemplateEngine());

        // 配置生成的Service包属性
        generator.strategyConfig(builder -> {
            Service.Builder serviceBuilder = builder.serviceBuilder();
            // 配置生成的Service接口名称
            // 生成的Service默认带有前缀I，如 IUserInfoService，这里配置去除前缀，也可以在这里加上自定义前缀
            serviceBuilder.formatServiceFileName("%sService");
            // 配置生成的Service实现类名称
            serviceBuilder.formatServiceImplFileName("%sServiceImp");
        });

        // 配置生成的Mapper包属性
        generator.strategyConfig(builder -> {
            Mapper.Builder mapperBuilder = builder.mapperBuilder();
            // 允许开启@Mapper注解，如果在主启动类上使用接口扫描，则这里无需使用此配置
            mapperBuilder.enableMapperAnnotation();
        });

        // 配置生成的Controller包属性
        generator.strategyConfig(builder -> {
            Controller.Builder controllerBuilder = builder.controllerBuilder();
            // 使用@RestController注解
            controllerBuilder.enableRestStyle();
        });

        // 配置生成的Entity包属性
        generator.strategyConfig(builder -> {
            Entity.Builder entityBuilder = builder.entityBuilder();
            // 禁止生成 serialVersionUID
            entityBuilder.disableSerialVersionUID();
            // 允许添加 Lombok 注解
            entityBuilder.enableLombok();
            // 允许生成 @TableId 或 @TableField 注解
            entityBuilder.enableTableFieldAnnotation();
        });

        // 钩子函数配置
        generator.injectionConfig(builder ->
                builder.beforeOutputFile((tableInfo, stringObjectMap) -> {
                    System.out.println("============== 表数据生成 ==============");
                    System.out.print("数据表名称：\t" + tableInfo.getName() + "\n");
                    System.out.print("数据表字段数：\t" + tableInfo.getFields().size() + "\n\n");
                })
        );

        generator.execute();
    }
}
